
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

const Size _kBubbleTriangleSizeH = Size(9.0, 16.0);
const Size _kBubbleTriangleSizeV = Size(18.0, 9.0);
const BorderRadius _kBubbleBorderRadius = BorderRadius.all(Radius.circular(7.5));

enum TLBubbleFrom { bottom, top, left, right }

class TLBubble extends StatelessWidget {

  TLBubble({
    Key key,
    this.backgroundColor = CupertinoColors.white,
    this.from = TLBubbleFrom.bottom,
    this.padding = const EdgeInsets.all(8.0),
    @required this.child
  }): super(key: key);

  final Color backgroundColor;
  final TLBubbleFrom from;
  final Widget child;
  final EdgeInsetsGeometry padding;

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    TLBubbleFrom _from = from;
    final TextDirection textDirection = Directionality.of(context);
    final bool isRtl = textDirection == TextDirection.rtl;
    final bool isHorizontal = (_from == TLBubbleFrom.left || _from == TLBubbleFrom.right);
    if (isRtl && isHorizontal) {
      _from = _from == TLBubbleFrom.left ? TLBubbleFrom.right : TLBubbleFrom.left;
    }

    // triangle
    final Size triangleSize =
    isHorizontal ? _kBubbleTriangleSizeH : _kBubbleTriangleSizeV;
    final Widget triangle = SizedBox.fromSize(
      size: triangleSize,
      child: CustomPaint(
        painter: _TLBubbleNotchPainter(pos: _from, backgroundColor: backgroundColor,),
      ),
    );
    // main rect
    final Widget rect = ClipRRect(
      borderRadius: _kBubbleBorderRadius,
      child: DecoratedBox(
        decoration: BoxDecoration(
          color: backgroundColor,
          borderRadius: _kBubbleBorderRadius,
          border: Border.all(color: backgroundColor, width: 0),
        ),
        child: Container(
          padding: padding,
          child: child,
        ),
      ),
    );

    if(from == TLBubbleFrom.bottom) {
      return Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          rect,
          triangle,
          const Padding(padding: const EdgeInsets.only(bottom: 8.0)),
        ],
      );
    } else if(from == TLBubbleFrom.top) {
      return Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          const Padding(padding: const EdgeInsets.only(top: 8.0)),
          triangle,
          rect,
        ],
      );
    } else if(from == TLBubbleFrom.left) {
      return Row(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          const Padding(padding: const EdgeInsets.only(left: 8.0)),
          triangle,
          rect,
        ],
      );
    } else {
      return Row(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          rect,
          triangle,
          const Padding(padding: const EdgeInsets.only(right: 8.0)),
        ],
      );
    }
  }

}

class _TLBubbleNotchPainter extends CustomPainter {

  _TLBubbleNotchPainter({this.pos, this.backgroundColor});

  final TLBubbleFrom pos;
  final Color backgroundColor;

  @override
  void paint(Canvas canvas, Size size) {
    final Paint paint = Paint()
        ..color = backgroundColor
        ..style = PaintingStyle.fill;

    Path triangle;
    if(pos == TLBubbleFrom.bottom) {
      triangle = Path()
          ..lineTo(size.width/2, 0.0)
          ..lineTo(0.0, size.height)
          ..lineTo(-size.width/2, 0.0)
          ..close();
    } else if(pos == TLBubbleFrom.top) {
      triangle = Path()
        ..lineTo(size.width / 2, size.height)
        ..lineTo(-(size.width / 2), size.height)
        ..close();
    } else if(pos == TLBubbleFrom.left) {
      triangle = Path()
        ..lineTo(size.width, size.height / 2)
        ..lineTo(size.width, -(size.height / 2))
        ..close();
    } else if(pos == TLBubbleFrom.right) {
      triangle = Path()
        ..lineTo(0.0, size.height / 2)
        ..lineTo(size.width, 0.0)
        ..lineTo(0.0, -(size.height / 2))
        ..close();
    }

    canvas.drawPath(triangle, paint);
  }

  @override
  bool shouldRepaint(_TLBubbleNotchPainter oldPainter) => false;
}